﻿using System;
using System.Windows;

namespace Tiny.Imaging.Filter.PixelLibrary
{
    public struct PixelUtil
    {
        public static double[] BezierMapping(Point start, Point ctrl1, Point ctrl2, Point end, int lowerBound = 0,
                                             int upperBound = 255)
        {
            var buffer = new double[1000];
            int bufferCount = 0;

            double cx = 3*(ctrl1.X - start.X);
            double bx = 3*(ctrl2.X - ctrl1.X) - cx;
            double ax = end.X - start.X - cx - bx;

            double cy = 3*(ctrl1.Y - start.Y);
            double by = 3*(ctrl2.Y - ctrl1.Y) - cy;
            double ay = end.Y - start.Y - cy - by;

            for (int i = 0; i < buffer.Length; ++i)
            {
                double t = i/1000.0;
                double t2 = t*t;
                double t3 = t*t*t;

                var curveX = (int) Math.Round((ax*t3) + (bx*t2) + (cx*t) + start.X);
                double curveY = (ay*t3) + (by*t2) + (cy*t) + start.Y;

                if (curveY < lowerBound)
                {
                    curveY = lowerBound;
                }
                else if (curveY > upperBound)
                {
                    curveY = upperBound;
                }

                buffer[curveX] = curveY;
                bufferCount++;
            }

            double lx = 0, ly = 0;
            double rx = 0, ry = 0;
            if (bufferCount < (int) (end.X + 1))
            {
                for (int i = 0; i <= (int) end.X; ++i)
                {
                    if (buffer[i] != -1)
                    {
                        lx = i - 1;
                        ly = buffer[i - 1];

                        for (int j = i + 1; j <= (int) end.X; ++j)
                        {
                            if (buffer[j] != -1)
                            {
                                rx = j;
                                ry = buffer[j];
                                break;
                            }
                        }

                        buffer[i] = ly + ((ry - ly)/(rx - lx))*(i - lx);
                    }
                }
            }

            if (buffer[(int) end.X] == -1)
            {
                buffer[(int) end.X] = buffer[254];
            }

            var result = new double[256];
            for (int i = 0; i < result.Length; ++i)
            {
                result[i] = buffer[i];
            }

            return result;
        }

        public static int[] CoordIndexMapping(int x, int y, int width, int height)
        {
            var results = new int[4];
            results[0] = x + y*width;
            results[1] = (width - x - 1) + y*width;
            results[2] = (width - x - 1) + (height - y - 1)*width;
            results[3] = x + (height - y - 1)*width;

            return results;
        }
    }
}